package com.acgist.snail.downloader.http;

import java.nio.channels.Channels;

import com.acgist.snail.context.ITaskSession;
import com.acgist.snail.downloader.MonofileDownloader;
import com.acgist.snail.logger.Logger;
import com.acgist.snail.logger.LoggerFactory;
import com.acgist.snail.net.NetException;
import com.acgist.snail.net.http.HttpClient;
import com.acgist.snail.utils.FileUtils;
import com.acgist.snail.utils.IoUtils;

/**
 * HTTP任务下载器
 * 
 * @author acgist
 */
public final class HttpDownloader extends MonofileDownloader {
	
	private static final Logger LOGGER = LoggerFactory.getLogger(HttpDownloader.class);

	/**
	 * @param taskSession 任务信息
	 */
	private HttpDownloader(ITaskSession taskSession) {
		super(taskSession);
	}

	/**
	 * @param taskSession 任务信息
	 * 
	 * @return {@link HttpDownloader}
	 */
	public static final HttpDownloader newInstance(ITaskSession taskSession) {
		return new HttpDownloader(taskSession);
	}
	
	@Override
	public void release() {
		IoUtils.close(this.input);
		IoUtils.close(this.output);
		super.release();
	}
	
	@Override
	protected void buildInput() throws NetException {
		// 连接
		final long downloadSize = FileUtils.fileSize(this.taskSession.getFile());
		final var client = HttpClient
			.newDownloader(this.taskSession.getUrl())
			.range(downloadSize)
			.get();
		if(client.downloadable()) {
			// 打开流
			final var headers = client.responseHeader();
			this.input = Channels.newChannel(client.response());
			// 断点续传
			if(headers.range()) {
				LOGGER.debug("HTTP断点下载：{}", downloadSize);
				this.taskSession.setDownloadSize(downloadSize);
			} else {
				LOGGER.debug("HTTP重新下载：{}", downloadSize);
				this.taskSession.setDownloadSize(0L);
			}
		} else if(this.taskSession.getDownloadSize() == this.taskSession.getSize()) {
			// 优先验证下载文件大小：416=超出请求范围
			this.completed = true;
		} else {
			this.fail("HTTP请求失败：" + client.code());
		}
	}

}
